package com.freight.common.core.interceptor;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.freight.common.core.constant.CacheConstants;
import com.freight.common.core.constant.Constants;
import com.freight.common.core.utils.Func;
import com.freight.common.core.utils.SecurityUtils;
import com.freight.common.core.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.beans.factory.SmartInitializingSingleton;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 租户信息处理器
 */
@Slf4j
@RequiredArgsConstructor
public class RybTenantHandler implements TenantLineHandler, SmartInitializingSingleton {

	/**
	 * 需要当做租户表处理的表名（加 @TableName注解且含有租户字段的表将被作为租户表）
	 */
	private final String[] myTenantTables = { "sys_user" };

	/**
	 * 匹配的多租户表（myTenantTables中自定义的表 + @TableName注解且含有租户字段的表）
	 */
	private final List<String> tenantTableList = new ArrayList<>(Arrays.asList(myTenantTables));

	/**
	 * 获取租户ID
	 *
	 * @return 租户ID
	 */
	@Override
	public Expression getTenantId() {
		return new StringValue(Func.toStr(SecurityUtils.getTenantId(), Constants.ADMIN_TENANT_ID));
	}

	/**
	 * 获取租户字段名称
	 *
	 * @return 租户字段名称
	 */
	@Override
	public String getTenantIdColumn() {
		return CacheConstants.TENANT_ID;
	}

	/**
	 * 根据表名判断是否忽略拼接多租户条件（默认都要进行解析并拼接多租户条件）
	 * @param tableName 表名
	 * @return 是否忽略, true:表示忽略，false:需要解析并拼接多租户条件
	 */
	@Override
	public boolean ignoreTable(String tableName) {
		if (RybTenantHolder.isIgnore()) {
			return true;
		}
		return !(tenantTableList.contains(tableName));
	}

	@Override
	public void afterSingletonsInstantiated() {
		// 获取所有 @TableName注解的表
		List<TableInfo> tableInfos = TableInfoHelper.getTableInfos();
		for (TableInfo tableInfo : tableInfos) {
			String tableName = tableInfo.getTableName();
			// 遍历字段
			List<TableFieldInfo> fieldList = tableInfo.getFieldList();
			// 如果含有租户字段
			TableFieldInfo tableFieldInfo = fieldList.stream().filter(fieldInfo -> getTenantIdColumn().equals(fieldInfo.getColumn())).findAny().orElse(null);
			if(StringUtils.isNotNull(tableFieldInfo) && !tenantTableList.contains(tableName)) {
				tenantTableList.add(tableName);
			}
		}
	}

}
